import java.io.Reader

import prolog.terms._

import prolog.fluents._

import prolog.io._

import java.io.Writer


class Builtins 

{
   
  def put(key:String,proto:Const){}
        
   
  def register(proto: Const) : Unit = 
   
  {
      
      var no :Int=2
      
      var key:String = proto.name+"/"+no
      
      put(key,proto)
   
   }

   
   def newBuiltin(S:Const):Const = 
   
   {
     
       var className:String = S.name 
     
       var no: Int=2
     
       var key:String = className+"/"+no
     
       var a:Const = get().asInstanceOf[Const]
     
       return a
   
     }


} 





class halt() extends ConstBuiltin("halt") 

{
  
    override def exec(p: Prog) = 
  
    {
    
           System.exit()
  
     }

}



class is_builtin() extends FunBuiltin("is_builtin", 1) 

{
  
     override def exec(p: Prog) = 
  
     {
   
           val a = getArg(0)
      a match 
      
            {
      
                   case _: ConstBuiltin => 1
     
                   case _: FunBuiltin => 1
      
                   case _ => 0
      
             }
  
       }

}


class compute extends FunBuiltin("compute",4)

{
  
  
    override def exec(p: Prog) 
  
    {
   
    
          val o=getArg(0)
    
          val a=getArg(1)
    
          val b=getArg(2)
    
          var opname : String =((Const)o).name()
    
          var x : double=((Num)a).getValue()
    
          var y : double=((Num)b).getValue()
    
          var r : double
    
          var op: char =opname.charAt(0)
      
    switch(op) 
          {
      
                   case _: + => r=x+y
      
 	case _: - => r=x-y
      
	case _: *=> r=x*y
      
      
	case _: / => r=x/y
      
	case _: % => r=x%y
      
	case _: ? => r=(x<y)?(-1):(x==y?0:1)
      
	case _: p => r=Math.pow(x,y)
      
	case _: l => r=Math.log(y)/Math.log(x)
      
	case _: r => r=x*Math.random()+y
      
	case _: < => r=(long)x<<(long)y
      
	case _: > => r=(long)x>>(long)y
     
    
           }
    
           var r: Num=((Math.floor(r)==r))?(Num)(new Int((long)r)):(Num)(new Real(r))
           return putArg(3,r,p)
      }

}


